package lb.io.apimachinery.runtime;

import com.google.protobuf.Message;
import lb.io.apimachinery.pkg.apis.meta.v1.*;
import lb.io.apimachinery.runtime.scheme.GroupVersion;
import lb.io.apimachinery.runtime.scheme.GroupVersionKind;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;

public class Plant {
    private Object object = null;

    private ObjectMeta meta = null;

    private GroupVersionKind gvk = null;

    public Plant(GroupVersionKind gvk, Object object)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        this.gvk = gvk;
        this.object = object;
        this.meta = (ObjectMeta) object.getClass().getDeclaredMethod("getMetadata").invoke(object);
    }

    /**
     * 返回 APIServerClient get 方法需要的参数
     *
     * @param contentType application/vk.linkBackup.protobuf
     * @return GetOptions
     */
    public GetOptions getOptions(String contentType) {
        return GetOptions.newBuilder()
                .setName(meta.getName())
                .setUid(meta.getUid())
                .setNamespace(meta.getNamespace())
                .setResourceVersion(meta.getResourceVersion())
                .setContentType(contentType)
                .setPrefix(meta.getPrefix())
                .setApiVersion(new GroupVersion(gvk.getGroup(), gvk.getVersion()).toString())
                .setKind(gvk.getKind())
                .build();
    }

    /**
     * 修改 Object 中的 ResourceVersion
     *
     * @param rv
     * @return
     */
    public Object setRV(String rv) {
        if (meta != null) {
            meta = meta.toBuilder().setResourceVersion(rv).build();
            try {
                Object builder = object.getClass().getDeclaredMethod("toBuilder").invoke(object);
                Object setter = builder.getClass().getDeclaredMethod("setMetadata", meta.getClass()).invoke(builder, meta);
                object = setter.getClass().getDeclaredMethod("build").invoke(setter);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return object;
    }

    /**
     * 返回 APIServerClient list 方法的参数
     *
     * @param contentType application/vk.linkBackup.protobuf
     * @param limit       返回个数
     * @param fields      查询的额外条件
     * @param _continue   上一次查询返回的 continue 参数，用于实现分页功能
     * @return ListOptions
     */
    public ListOptions listOptions(String contentType, int limit, Map<String, String> fields, String _continue) {
        return ListOptions.newBuilder()
                .setLimit(limit)
                .setContinue(_continue)
                .putAllLabels(meta.getLabelsMap())
                .putAllFields(fields)
                .setNamespace(meta.getNamespace())
                .setResourceVersion(meta.getResourceVersion())
                .setContentType(contentType)
                .setPrefix(meta.getPrefix())
                .setApiVersion(new GroupVersion(gvk.getGroup(), gvk.getVersion()).toString())
                .setKind(gvk.getKind())
                .build();
    }

    /**
     * 返回 APIServerClient post 方法的参数
     *
     * @param contentType application/vk.linkBackup.protobuf
     * @param ttl         etcd 中 key 的生存周期，单位为 s
     * @return PostOptions
     */
    public PostOptions postOptions(String contentType, int ttl) {
        Message message = (Message) object;
        return PostOptions.newBuilder()
                .setName(meta.getName())
                .setUid(meta.getUid())
                .setNamespace(meta.getNamespace())
                .setResourceVersion(meta.getResourceVersion())
                .setContentType(contentType)
                .setPrefix(meta.getPrefix())
                .setTtl(ttl)
                .setApiVersion(new GroupVersion(gvk.getGroup(), gvk.getVersion()).toString())
                .setKind(gvk.getKind())
                .setRaws(message.toByteString())
                .build();
    }

    /**
     * 返回 APIServerClient patch 方法的参数
     *
     * @param contentType application/vk.linkBackup.protobuf
     * @param ttl         etcd 中 key 的生成周期，单位为 s
     * @return PatchOptions
     */
    public PatchOptions patchOptions(String contentType, int ttl) {
        Message message = (Message) object;
        return PatchOptions.newBuilder()
                .setName(meta.getName())
                .setUid(meta.getUid())
                .setNamespace(meta.getNamespace())
                .setResourceVersion(meta.getResourceVersion())
                .setContentType(contentType)
                .setPrefix(meta.getPrefix())
                .setTtl(ttl)
                .setApiVersion(new GroupVersion(gvk.getGroup(), gvk.getVersion()).toString())
                .setKind(gvk.getKind())
                .setRaws(message.toByteString())
                .build();
    }

    /**
     * 返回 APIServerClient delete 的参数
     *
     * @param contentType application/vk.linkBackup.protobuf
     * @return DeleteOptions
     */
    public DeleteOptions deleteOptions(String contentType) {
        return DeleteOptions.newBuilder()
                .setName(meta.getName())
                .setUid(meta.getUid())
                .setNamespace(meta.getNamespace())
                .setResourceVersion(meta.getResourceVersion())
                .setContentType(contentType)
                .setPrefix(meta.getPrefix())
                .setApiVersion(new GroupVersion(gvk.getGroup(), gvk.getVersion()).toString())
                .setKind(gvk.getKind())
                .build();
    }

    /***
     * 返回 APIServerClient readyz 的参数
     *
     * @param contentType application/vk.linkBackup.protobuf
     * @param ttl 资源的生命周期，单位秒
     * @return ObjectRaws
     */
    public ObjectRaws raws(String contentType, int ttl) {
        Message message = (Message) object;
        return ObjectRaws.newBuilder()
                .setResourceVersion(meta.getResourceVersion())
                .setApiVersion(new GroupVersion(gvk.getGroup(), gvk.getVersion()).toString())
                .setKind(gvk.getKind())
                .setContentType(contentType)
                .setTtl(ttl)
                .setRaws(message.toByteString())
                .build();
    }
}
